Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


RNS/Destination.py HEAD (3535327f) Text, 31.54 KB

T8b949e# Reticulum License
T8b949e#
T8b949e# Copyright (c) 2016-2025 Mark Qvist
T8b949e#
T8b949e# Permission is hereby granted, free of charge, to any person obtaining a copy
T8b949e# of this software and associated documentation files (the "Software"), to deal
T8b949e# in the Software without restriction, including without limitation the rights
T8b949e# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
T8b949e# copies of the Software, and to permit persons to whom the Software is
T8b949e# furnished to do so, subject to the following conditions:
T8b949e#
T8b949e# - The Software shall not be used in any kind of system which includes amongst
T8b949e# its functions the ability to purposefully do harm to human beings.
T8b949e#
T8b949e# - The Software shall not be used, directly or indirectly, in the creation of
T8b949e# an artificial intelligence, machine learning or language model training
T8b949e# dataset, including but not limited to any use that contributes to the
T8b949e# training or development of such a model or algorithm.
T8b949e#
T8b949e# - The above copyright notice and this permission notice shall be included in
T8b949e# all copies or substantial portions of the Software.
T8b949e#
T8b949e# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
T8b949e# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
T8b949e# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
T8b949e# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
T8b949e# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
T8b949e# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
T8b949e# SOFTWARE.

Tff7b72import T7ee787os
Tff7b72import T7ee787math
Tff7b72import T7ee787time
Tff7b72import T7ee787threading
Tff7b72import T7ee787RNS

Tff7b72from T7ee787RNST7ee787.T7ee787Cryptography Tff7b72import Te6edf3Token
Tff7b72from T7ee787.T7ee787vendor Tff7b72import Te6edf3umsgpack Tff7b72as Te6edf3umsgpack

Tff7b72class T56d364CallbacksTb4b4b4:
Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8fflink_established Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffpacket Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffproof_requested Tff7b72= Tff7b72None

Tff7b72class T56d364DestinationTb4b4b4:
T8b949e"""
A class used to describe endpoints in a Reticulum Network. Destination
instances are used both to create outgoing and incoming endpoints. The
destination type will decide if encryption, and what type, is used in
communication with the endpoint. A destination can also announce its
presence on the network, which will distribute necessary keys for
encrypted communication with it.

:param identity: An instance of :ref:`RNS.Identity<api-identity>`. Can hold only public keys for an outgoing destination, or holding private keys for an ingoing.
:param direction: ``RNS.Destination.IN`` or ``RNS.Destination.OUT``.
:param type: ``RNS.Destination.SINGLE``, ``RNS.Destination.GROUP`` or ``RNS.Destination.PLAIN``.
:param app_name: A string specifying the app name.
:param \\*aspects: Any non-zero number of string arguments.
"""

T8b949e# Constants
Te6edf3SINGLE Tff7b72= T79c0ff0x00
Te6edf3GROUP Tff7b72= T79c0ff0x01
Te6edf3PLAIN Tff7b72= T79c0ff0x02
Te6edf3LINK Tff7b72= T79c0ff0x03
Te6edf3types Tff7b72= Tb4b4b4[Te6edf3SINGLETb4b4b4, Te6edf3GROUPTb4b4b4, Te6edf3PLAINTb4b4b4, Te6edf3LINKTb4b4b4]

Te6edf3PROVE_NONE Tff7b72= T79c0ff0x21
Te6edf3PROVE_APP Tff7b72= T79c0ff0x22
Te6edf3PROVE_ALL Tff7b72= T79c0ff0x23
Te6edf3proof_strategies Tff7b72= Tb4b4b4[Te6edf3PROVE_NONETb4b4b4, Te6edf3PROVE_APPTb4b4b4, Te6edf3PROVE_ALLTb4b4b4]

Te6edf3ALLOW_NONE Tff7b72= T79c0ff0x00
Te6edf3ALLOW_ALL Tff7b72= T79c0ff0x01
Te6edf3ALLOW_LIST Tff7b72= T79c0ff0x02
Te6edf3request_policies Tff7b72= Tb4b4b4[Te6edf3ALLOW_NONETb4b4b4, Te6edf3ALLOW_ALLTb4b4b4, Te6edf3ALLOW_LISTTb4b4b4]

Te6edf3IN Tff7b72= T79c0ff0x11Tb4b4b4;
Te6edf3OUT Tff7b72= T79c0ff0x12Tb4b4b4;
Te6edf3directions Tff7b72= Tb4b4b4[Te6edf3INTb4b4b4, Te6edf3OUTTb4b4b4]

Te6edf3PR_TAG_WINDOW Tff7b72= T79c0ff30

Te6edf3RATCHET_COUNT Tff7b72= T79c0ff512
T8b949e"""
The default number of generated ratchet keys a destination will retain, if it has ratchets enabled.
"""

Te6edf3RATCHET_INTERVAL Tff7b72= T79c0ff30Tff7b72*T79c0ff60
T8b949e"""
The minimum interval between rotating ratchet keys, in seconds.
"""

Tf0883e@staticmethod
Tff7b72def Td2a8ffexpand_nameTb4b4b4(Te6edf3identityTb4b4b4, Te6edf3app_nameTb4b4b4, Tff7b72*Te6edf3aspectsTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: A string containing the full human-readable name of the destination, for an app_name and a number of aspects.
"""

T8b949e# Check input values and build name string
Tff7b72if Ta5d6ff"Ta5d6ff.Ta5d6ff" Tff7b72in Te6edf3app_nameTb4b4b4: Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffDots canTa5d6ff'Ta5d6fft be used in app namesTa5d6ff"Tb4b4b4)

Te6edf3name Tff7b72= Te6edf3app_name
Tff7b72for Te6edf3aspect Tff7b72in Te6edf3aspectsTb4b4b4:
Tff7b72if Ta5d6ff"Ta5d6ff.Ta5d6ff" Tff7b72in Te6edf3aspectTb4b4b4: Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffDots canTa5d6ff'Ta5d6fft be used in aspectsTa5d6ff"Tb4b4b4)
Te6edf3name Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ff.Ta5d6ff" Tff7b72+ Te6edf3aspect

Tff7b72if Te6edf3identity Tff7b72!= Tff7b72NoneTb4b4b4:
Te6edf3name Tff7b72+Tff7b72= Ta5d6ff"Ta5d6ff.Ta5d6ff" Tff7b72+ Te6edf3identityTff7b72.Td2a8ffhexhash

Tff7b72return Te6edf3name


Tf0883e@staticmethod
Tff7b72def Td2a8ffhashTb4b4b4(Te6edf3identityTb4b4b4, Te6edf3app_nameTb4b4b4, Tff7b72*Te6edf3aspectsTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: A destination name in adressable hash form, for an app_name and a number of aspects.
"""
Te6edf3name_hash Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fffull_hashTb4b4b4(Te6edf3DestinationTff7b72.Td2a8ffexpand_nameTb4b4b4(Tff7b72NoneTb4b4b4, Te6edf3app_nameTb4b4b4, Tff7b72*Te6edf3aspectsTb4b4b4)Tff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4[Tb4b4b4:Tb4b4b4(Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffNAME_HASH_LENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4)Tb4b4b4]
Te6edf3addr_hash_material Tff7b72= Te6edf3name_hash
Tff7b72if Te6edf3identity Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3identityTb4b4b4, Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4)Tb4b4b4:
Te6edf3addr_hash_material Tff7b72+Tff7b72= Te6edf3identityTff7b72.Td2a8ffhash
Tff7b72elif Tffa657isinstanceTb4b4b4(Te6edf3identityTb4b4b4, Tffa657bytesTb4b4b4) Tff7b72and Tffa657lenTb4b4b4(Te6edf3identityTb4b4b4) Tff7b72== Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffTRUNCATED_HASHLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4:
Te6edf3addr_hash_material Tff7b72+Tff7b72= Te6edf3identity
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid material supplied for destination hash calculationTa5d6ff"Tb4b4b4)

Tff7b72return Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fffull_hashTb4b4b4(Te6edf3addr_hash_materialTb4b4b4)Tb4b4b4[Tb4b4b4:Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffTRUNCATED_HASHLENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4]

Tf0883e@staticmethod
Tff7b72def Td2a8ffapp_and_aspects_from_nameTb4b4b4(Te6edf3full_nameTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: A tuple containing the app name and a list of aspects, for a full-name string.
"""
Te6edf3components Tff7b72= Te6edf3full_nameTff7b72.Td2a8ffsplitTb4b4b4(Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4)
Tff7b72return Tb4b4b4(Te6edf3componentsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4, Te6edf3componentsTb4b4b4[T79c0ff1Tb4b4b4:Tb4b4b4]Tb4b4b4)

Tf0883e@staticmethod
Tff7b72def Td2a8ffhash_from_name_and_identityTb4b4b4(Te6edf3full_nameTb4b4b4, Te6edf3identityTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: A destination name in adressable hash form, for a full name string and Identity instance.
"""
Te6edf3app_nameTb4b4b4, Te6edf3aspects Tff7b72= Te6edf3DestinationTff7b72.Td2a8ffapp_and_aspects_from_nameTb4b4b4(Te6edf3full_nameTb4b4b4)

Tff7b72return Te6edf3DestinationTff7b72.Td2a8ffhashTb4b4b4(Te6edf3identityTb4b4b4, Te6edf3app_nameTb4b4b4, Tff7b72*Te6edf3aspectsTb4b4b4)

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identityTb4b4b4, Te6edf3directionTb4b4b4, Tffa657typeTb4b4b4, Te6edf3app_nameTb4b4b4, Tff7b72*Te6edf3aspectsTb4b4b4)Tb4b4b4:
T8b949e# Check input values and build name string
Tff7b72if Ta5d6ff"Ta5d6ff.Ta5d6ff" Tff7b72in Te6edf3app_nameTb4b4b4: Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffDots canTa5d6ff'Ta5d6fft be used in app namesTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657type Tff7b72in Te6edf3DestinationTff7b72.Td2a8fftypesTb4b4b4: Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffUnknown destination typeTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3direction Tff7b72in Te6edf3DestinationTff7b72.Td2a8ffdirectionsTb4b4b4: Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffUnknown destination directionTa5d6ff"Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffaccept_link_requests Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ffcallbacks Tff7b72= Te6edf3CallbacksTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrequest_handlers Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8fftype Tff7b72= Tffa657type
Tff7b72selfTff7b72.Td2a8ffdirection Tff7b72= Te6edf3direction
Tff7b72selfTff7b72.Td2a8ffproof_strategy Tff7b72= Te6edf3DestinationTff7b72.Td2a8ffPROVE_NONE
Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffratchets_path Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffratchet_interval Tff7b72= Te6edf3DestinationTff7b72.Td2a8ffRATCHET_INTERVAL
Tff7b72selfTff7b72.Td2a8ffratchet_file_lock Tff7b72= Te6edf3threadingTff7b72.Td2a8ffLockTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffretained_ratchets Tff7b72= Te6edf3DestinationTff7b72.Td2a8ffRATCHET_COUNT
Tff7b72selfTff7b72.Td2a8fflatest_ratchet_time Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8fflatest_ratchet_id Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ff__enforce_ratchets Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ffmtu Tff7b72= T79c0ff0

Tff7b72selfTff7b72.Td2a8ffpath_responses Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8fflinks Tff7b72= Tb4b4b4[Tb4b4b4]

Tff7b72if Te6edf3identity Tff7b72== Tff7b72None Tff7b72and Te6edf3direction Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffIN Tff7b72and Tff7b72selfTff7b72.Td2a8fftype Tff7b72!= Te6edf3DestinationTff7b72.Td2a8ffPLAINTb4b4b4:
Te6edf3identity Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTb4b4b4(Tb4b4b4)
Te6edf3aspects Tff7b72= Te6edf3aspectsTff7b72+Tb4b4b4(Te6edf3identityTff7b72.Td2a8ffhexhashTb4b4b4,Tb4b4b4)

Tff7b72if Te6edf3identity Tff7b72== Tff7b72None Tff7b72and Te6edf3direction Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffOUT Tff7b72and Tff7b72selfTff7b72.Td2a8fftype Tff7b72!= Te6edf3DestinationTff7b72.Td2a8ffPLAINTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffCanTa5d6ff'Ta5d6fft create outbound SINGLE destination without an identityTa5d6ff"Tb4b4b4)

Tff7b72if Te6edf3identity Tff7b72!= Tff7b72None Tff7b72and Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffPLAINTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffSelected destination type PLAIN cannot hold an identityTa5d6ff"Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72= Te6edf3identity
Tff7b72selfTff7b72.Td2a8ffname Tff7b72= Te6edf3DestinationTff7b72.Td2a8ffexpand_nameTb4b4b4(Te6edf3identityTb4b4b4, Te6edf3app_nameTb4b4b4, Tff7b72*Te6edf3aspectsTb4b4b4)

T8b949e# Generate the destination address hash
Tff7b72selfTff7b72.Td2a8ffhash Tff7b72= Te6edf3DestinationTff7b72.Td2a8ffhashTb4b4b4(Tff7b72selfTff7b72.Td2a8ffidentityTb4b4b4, Te6edf3app_nameTb4b4b4, Tff7b72*Te6edf3aspectsTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffname_hash Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fffull_hashTb4b4b4(Tff7b72selfTff7b72.Td2a8ffexpand_nameTb4b4b4(Tff7b72NoneTb4b4b4, Te6edf3app_nameTb4b4b4, Tff7b72*Te6edf3aspectsTb4b4b4)Tff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4[Tb4b4b4:Tb4b4b4(Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffNAME_HASH_LENGTHTff7b72/Tff7b72/T79c0ff8Tb4b4b4)Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffhexhash Tff7b72= Tff7b72selfTff7b72.Td2a8ffhashTff7b72.Td2a8ffhexTb4b4b4(Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffdefault_app_data Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffcallback Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffproofcallback Tff7b72= Tff7b72None

Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffregister_destinationTb4b4b4(Tff7b72selfTb4b4b4)


Tff7b72def Tff7b72__str__Tb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
:returns: A human-readable representation of the destination including addressable hash and full name.
"""
Tff7b72return Ta5d6ff"Ta5d6ff<Ta5d6ff"Tff7b72+Tff7b72selfTff7b72.Td2a8ffnameTff7b72+Ta5d6ff"Ta5d6ff:Ta5d6ff"Tff7b72+Tff7b72selfTff7b72.Td2a8ffhexhashTff7b72+Ta5d6ff"Ta5d6ff>Ta5d6ff"

Tff7b72def Td2a8ff_clean_ratchetsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72if Tffa657len Tb4b4b4(Tff7b72selfTff7b72.Td2a8ffratchetsTb4b4b4) Tff7b72> Tff7b72selfTff7b72.Td2a8ffretained_ratchetsTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72= Tff7b72selfTff7b72.Td2a8ffratchetsTb4b4b4[Tb4b4b4:Te6edf3DestinationTff7b72.Td2a8ffRATCHET_COUNTTb4b4b4]

Tff7b72def Td2a8ff_persist_ratchetsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ffratchet_file_lockTb4b4b4:
Te6edf3temp_write_path Tff7b72= Tff7b72selfTff7b72.Td2a8ffratchets_pathTff7b72+Ta5d6ff"Ta5d6ff.tmpTa5d6ff"
Te6edf3packed_ratchets Tff7b72= Te6edf3umsgpackTff7b72.Td2a8ffpackbTb4b4b4(Tff7b72selfTff7b72.Td2a8ffratchetsTb4b4b4)
Te6edf3persisted_data Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffsignatureTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffsignTb4b4b4(Te6edf3packed_ratchetsTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffratchetsTa5d6ff"Tb4b4b4: Te6edf3packed_ratchetsTb4b4b4}
Te6edf3ratchets_file Tff7b72= Tffa657openTb4b4b4(Te6edf3temp_write_pathTb4b4b4, Ta5d6ff"Ta5d6ffwbTa5d6ff"Tb4b4b4)
Te6edf3ratchets_fileTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3umsgpackTff7b72.Td2a8ffpackbTb4b4b4(Te6edf3persisted_dataTb4b4b4)Tb4b4b4)
Te6edf3ratchets_fileTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Tff7b72selfTff7b72.Td2a8ffratchets_pathTb4b4b4)Tb4b4b4: Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Tff7b72selfTff7b72.Td2a8ffratchets_pathTb4b4b4)
Te6edf3osTff7b72.Td2a8ffrenameTb4b4b4(Te6edf3temp_write_pathTb4b4b4, Tff7b72selfTff7b72.Td2a8ffratchets_pathTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fftrace_exceptionTb4b4b4(Te6edf3eTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffratchets_path Tff7b72= Tff7b72None
Tff7b72raise Tf85149OSErrorTb4b4b4(Ta5d6ff"Ta5d6ffCould not write ratchet file contents for Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTb4b4b4)Tff7b72+Ta5d6ff"Ta5d6ff. The contained exception was: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)

Tff7b72def Td2a8ffrotate_ratchetsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72!= Tff7b72NoneTb4b4b4:
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3now Tff7b72> Tff7b72selfTff7b72.Td2a8fflatest_ratchet_timeTff7b72+Tff7b72selfTff7b72.Td2a8ffratchet_intervalTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffRotating ratchets for Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Te6edf3new_ratchet Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ff_generate_ratchetTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffratchetsTff7b72.Td2a8ffinsertTb4b4b4(T79c0ff0Tb4b4b4, Te6edf3new_ratchetTb4b4b4)
Tff7b72selfTff7b72.Td2a8fflatest_ratchet_time Tff7b72= Te6edf3now
Tff7b72selfTff7b72.Td2a8ff_clean_ratchetsTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_persist_ratchetsTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149SystemErrorTb4b4b4(Ta5d6ff"Ta5d6ffCannot rotate ratchet on Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTb4b4b4)Tff7b72+Ta5d6ff"Ta5d6ff, ratchets are not enabledTa5d6ff"Tb4b4b4)

Tff7b72return Tff7b72False

Tff7b72def Td2a8ffannounceTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3app_dataTff7b72=Tff7b72NoneTb4b4b4, Te6edf3path_responseTff7b72=Tff7b72FalseTb4b4b4, Te6edf3attached_interfaceTff7b72=Tff7b72NoneTb4b4b4, Te6edf3tagTff7b72=Tff7b72NoneTb4b4b4, Te6edf3sendTff7b72=Tff7b72TrueTb4b4b4)Tb4b4b4:
T8b949e"""
Creates an announce packet for this destination and broadcasts it on all
relevant interfaces. Application specific data can be added to the announce.

:param app_data: *bytes* containing the app_data.
:param path_response: Internal flag used by :ref:`RNS.Transport<api-transport>`. Ignore.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72!= Te6edf3DestinationTff7b72.Td2a8ffSINGLETb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffOnly SINGLE destination types can be announcedTa5d6ff"Tb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8ffdirection Tff7b72!= Te6edf3DestinationTff7b72.Td2a8ffINTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffOnly IN destination types can be announcedTa5d6ff"Tb4b4b4)
Te6edf3ratchet Tff7b72= Ta5d6ffbTa5d6ff"Ta5d6ff"
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3stale_responses Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3entry_tag Tff7b72in Tff7b72selfTff7b72.Td2a8ffpath_responsesTb4b4b4:
Te6edf3entry Tff7b72= Tff7b72selfTff7b72.Td2a8ffpath_responsesTb4b4b4[Te6edf3entry_tagTb4b4b4]
Tff7b72if Te6edf3now Tff7b72> Te6edf3entryTb4b4b4[T79c0ff0Tb4b4b4]Tff7b72+Te6edf3DestinationTff7b72.Td2a8ffPR_TAG_WINDOWTb4b4b4:
Te6edf3stale_responsesTff7b72.Td2a8ffappendTb4b4b4(Te6edf3entry_tagTb4b4b4)

Tff7b72for Te6edf3entry_tag Tff7b72in Te6edf3stale_responsesTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpath_responsesTff7b72.Td2a8ffpopTb4b4b4(Te6edf3entry_tagTb4b4b4)

Tff7b72if Tb4b4b4(Te6edf3path_response Tff7b72== Tff7b72True Tff7b72and Te6edf3tag Tff7b72!= Tff7b72NoneTb4b4b4) Tff7b72and Te6edf3tag Tff7b72in Tff7b72selfTff7b72.Td2a8ffpath_responsesTb4b4b4:
T8b949e# This code is currently not used, since Transport will block duplicate
T8b949e# path requests based on tags. When multi-path support is implemented in
T8b949e# Transport, this will allow Transport to detect redundant paths to the
T8b949e# same destination, and select the best one based on chosen criteria,
T8b949e# since it will be able to detect that a single emitted announce was
T8b949e# received via multiple paths. The difference in reception time will
T8b949e# potentially also be useful in determining characteristics of the
T8b949e# multiple available paths, and to choose the best one.
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffUsing cached announce data for answering path request with tag Ta5d6ff"Tff7b72+Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Te6edf3tagTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_EXTREMETb4b4b4)
Te6edf3announce_data Tff7b72= Tff7b72selfTff7b72.Td2a8ffpath_responsesTb4b4b4[Te6edf3tagTb4b4b4]Tb4b4b4[T79c0ff1Tb4b4b4]
Tff7b72elseTb4b4b4:
Te6edf3destination_hash Tff7b72= Tff7b72selfTff7b72.Td2a8ffhash
Te6edf3random_hash Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffget_random_hashTb4b4b4(Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4:T79c0ff5Tb4b4b4]Tff7b72+Tffa657intTb4b4b4(Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72.Td2a8ffto_bytesTb4b4b4(T79c0ff5Tb4b4b4, Ta5d6ff"Ta5d6ffbigTa5d6ff"Tb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrotate_ratchetsTb4b4b4(Tb4b4b4)
Te6edf3ratchet Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ff_ratchet_public_bytesTb4b4b4(Tff7b72selfTff7b72.Td2a8ffratchetsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)
Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ff_remember_ratchetTb4b4b4(Tff7b72selfTff7b72.Td2a8ffhashTb4b4b4, Te6edf3ratchetTb4b4b4)

Tff7b72if Te6edf3app_data Tff7b72== Tff7b72None Tff7b72and Tff7b72selfTff7b72.Td2a8ffdefault_app_data Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72if Tffa657isinstanceTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdefault_app_dataTb4b4b4, Tffa657bytesTb4b4b4)Tb4b4b4:
Te6edf3app_data Tff7b72= Tff7b72selfTff7b72.Td2a8ffdefault_app_data
Tff7b72elif Tffa657callableTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdefault_app_dataTb4b4b4)Tb4b4b4:
Te6edf3returned_app_data Tff7b72= Tff7b72selfTff7b72.Td2a8ffdefault_app_dataTb4b4b4(Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3returned_app_dataTb4b4b4, Tffa657bytesTb4b4b4)Tb4b4b4:
Te6edf3app_data Tff7b72= Te6edf3returned_app_data
Te6edf3signed_data Tff7b72= Tff7b72selfTff7b72.Td2a8ffhashTff7b72+Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffget_public_keyTb4b4b4(Tb4b4b4)Tff7b72+Tff7b72selfTff7b72.Td2a8ffname_hashTff7b72+Te6edf3random_hashTff7b72+Te6edf3ratchet
Tff7b72if Te6edf3app_data Tff7b72!= Tff7b72NoneTb4b4b4: Te6edf3signed_data Tff7b72+Tff7b72= Te6edf3app_data

Te6edf3signature Tff7b72= Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffsignTb4b4b4(Te6edf3signed_dataTb4b4b4)
Te6edf3announce_data Tff7b72= Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffget_public_keyTb4b4b4(Tb4b4b4)Tff7b72+Tff7b72selfTff7b72.Td2a8ffname_hashTff7b72+Te6edf3random_hashTff7b72+Te6edf3ratchetTff7b72+Te6edf3signature

Tff7b72if Te6edf3app_data Tff7b72!= Tff7b72NoneTb4b4b4: Te6edf3announce_data Tff7b72+Tff7b72= Te6edf3app_data

Tff7b72selfTff7b72.Td2a8ffpath_responsesTb4b4b4[Te6edf3tagTb4b4b4] Tff7b72= Tb4b4b4[Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3announce_dataTb4b4b4]

Tff7b72if Te6edf3path_responseTb4b4b4: Te6edf3announce_context Tff7b72= Te6edf3RNSTff7b72.Td2a8ffPacketTff7b72.Td2a8ffPATH_RESPONSE
Tff7b72elseTb4b4b4: Te6edf3announce_context Tff7b72= Te6edf3RNSTff7b72.Td2a8ffPacketTff7b72.Td2a8ffNONE

Tff7b72if Te6edf3ratchetTb4b4b4: Te6edf3context_flag Tff7b72= Te6edf3RNSTff7b72.Td2a8ffPacketTff7b72.Td2a8ffFLAG_SET
Tff7b72elseTb4b4b4: Te6edf3context_flag Tff7b72= Te6edf3RNSTff7b72.Td2a8ffPacketTff7b72.Td2a8ffFLAG_UNSET

Te6edf3announce_packet Tff7b72= Te6edf3RNSTff7b72.Td2a8ffPacketTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3announce_dataTb4b4b4, Te6edf3RNSTff7b72.Td2a8ffPacketTff7b72.Td2a8ffANNOUNCETb4b4b4, Te6edf3context Tff7b72= Te6edf3announce_contextTb4b4b4,
Te6edf3attached_interface Tff7b72= Te6edf3attached_interfaceTb4b4b4, Te6edf3context_flagTff7b72=Te6edf3context_flagTb4b4b4)
Tff7b72if Te6edf3sendTb4b4b4: Te6edf3announce_packetTff7b72.Td2a8ffsendTb4b4b4(Tb4b4b4)
Tff7b72elseTb4b4b4: Tff7b72return Te6edf3announce_packet

Tff7b72def Td2a8ffaccepts_linksTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3accepts Tff7b72= Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e"""
Set or query whether the destination accepts incoming link requests.

:param accepts: If ``True`` or ``False``, this method sets whether the destination accepts incoming link requests. If not provided or ``None``, the method returns whether the destination currently accepts link requests.
:returns: ``True`` or ``False`` depending on whether the destination accepts incoming link requests, if the *accepts* parameter is not provided or ``None``.
"""
Tff7b72if Te6edf3accepts Tff7b72== Tff7b72NoneTb4b4b4: Tff7b72return Tff7b72selfTff7b72.Td2a8ffaccept_link_requests

Tff7b72if Te6edf3acceptsTb4b4b4: Tff7b72selfTff7b72.Td2a8ffaccept_link_requests Tff7b72= Tff7b72True
Tff7b72elseTb4b4b4: Tff7b72selfTff7b72.Td2a8ffaccept_link_requests Tff7b72= Tff7b72False

Tff7b72def Td2a8ffset_link_established_callbackTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3callbackTb4b4b4)Tb4b4b4:
T8b949e"""
Registers a function to be called when a link has been established to
this destination.

:param callback: A function or method with the signature *callback(link)* to be called when a new link is established with this destination.
"""
Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8fflink_established Tff7b72= Te6edf3callback

Tff7b72def Td2a8ffset_packet_callbackTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3callbackTb4b4b4)Tb4b4b4:
T8b949e"""
Registers a function to be called when a packet has been received by
this destination.

:param callback: A function or method with the signature *callback(data, packet)* to be called when this destination receives a packet.
"""
Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffpacket Tff7b72= Te6edf3callback

Tff7b72def Td2a8ffset_proof_requested_callbackTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3callbackTb4b4b4)Tb4b4b4:
T8b949e"""
Registers a function to be called when a proof has been requested for
a packet sent to this destination. Allows control over when and if
proofs should be returned for received packets.

:param callback: A function or method to with the signature *callback(packet)* be called when a packet that requests a proof is received. The callback must return one of True or False. If the callback returns True, a proof will be sent. If it returns False, a proof will not be sent.
"""
Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffproof_requested Tff7b72= Te6edf3callback

Tff7b72def Td2a8ffset_proof_strategyTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3proof_strategyTb4b4b4)Tb4b4b4:
T8b949e"""
Sets the destinations proof strategy.

:param proof_strategy: One of ``RNS.Destination.PROVE_NONE``, ``RNS.Destination.PROVE_ALL`` or ``RNS.Destination.PROVE_APP``. If ``RNS.Destination.PROVE_APP`` is set, the `proof_requested_callback` will be called to determine whether a proof should be sent or not.
"""
Tff7b72if Tff7b72not Te6edf3proof_strategy Tff7b72in Te6edf3DestinationTff7b72.Td2a8ffproof_strategiesTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffUnsupported proof strategyTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffproof_strategy Tff7b72= Te6edf3proof_strategy

Tff7b72def Td2a8ffregister_request_handlerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pathTb4b4b4, Te6edf3response_generator Tff7b72= Tff7b72NoneTb4b4b4, Te6edf3allow Tff7b72= Te6edf3ALLOW_NONETb4b4b4, Te6edf3allowed_list Tff7b72= Tff7b72NoneTb4b4b4, Te6edf3auto_compress Tff7b72= Tff7b72TrueTb4b4b4)Tb4b4b4:
T8b949e"""
Registers a request handler.

:param path: The path for the request handler to be registered.
:param response_generator: A function or method with the signature *response_generator(path, data, request_id, link_id, remote_identity, requested_at)* to be called. Whatever this funcion returns will be sent as a response to the requester. If the function returns ``None``, no response will be sent.
:param allow: One of ``RNS.Destination.ALLOW_NONE``, ``RNS.Destination.ALLOW_ALL`` or ``RNS.Destination.ALLOW_LIST``. If ``RNS.Destination.ALLOW_LIST`` is set, the request handler will only respond to requests for identified peers in the supplied list.
:param allowed_list: A list of *bytes-like* :ref:`RNS.Identity<api-identity>` hashes.
:param auto_compress: If ``True`` or ``False``, determines whether automatic compression of responses should be carried out. If set to an integer value, responses will only be auto-compressed if under this size in bytes. If omitted, the default compression settings will be followed.
:raises: ``ValueError`` if any of the supplied arguments are invalid.
"""
Tff7b72if Te6edf3path Tff7b72== Tff7b72None Tff7b72or Te6edf3path Tff7b72== Ta5d6ff"Ta5d6ff"Tb4b4b4: Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid path specifiedTa5d6ff"Tb4b4b4)
Tff7b72elif Tff7b72not Tffa657callableTb4b4b4(Te6edf3response_generatorTb4b4b4)Tb4b4b4: Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid response generator specifiedTa5d6ff"Tb4b4b4)
Tff7b72elif Tff7b72not Te6edf3allow Tff7b72in Te6edf3DestinationTff7b72.Td2a8ffrequest_policiesTb4b4b4: Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid request policyTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3path_hash Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fftruncated_hashTb4b4b4(Te6edf3pathTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3request_handler Tff7b72= Tb4b4b4[Te6edf3pathTb4b4b4, Te6edf3response_generatorTb4b4b4, Te6edf3allowTb4b4b4, Te6edf3allowed_listTb4b4b4, Te6edf3auto_compressTb4b4b4]
Tff7b72selfTff7b72.Td2a8ffrequest_handlersTb4b4b4[Te6edf3path_hashTb4b4b4] Tff7b72= Te6edf3request_handler

Tff7b72def Td2a8ffderegister_request_handlerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pathTb4b4b4)Tb4b4b4:
T8b949e"""
Deregisters a request handler.

:param path: The path for the request handler to be deregistered.
:returns: True if the handler was deregistered, otherwise False.
"""
Te6edf3path_hash Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8fftruncated_hashTb4b4b4(Te6edf3pathTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72if Te6edf3path_hash Tff7b72in Tff7b72selfTff7b72.Td2a8ffrequest_handlersTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrequest_handlersTff7b72.Td2a8ffpopTb4b4b4(Te6edf3path_hashTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffreceiveTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3packetTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3packetTff7b72.Td2a8ffpacket_type Tff7b72== Te6edf3RNSTff7b72.Td2a8ffPacketTff7b72.Td2a8ffLINKREQUESTTb4b4b4:
Te6edf3plaintext Tff7b72= Te6edf3packetTff7b72.Td2a8ffdata
Tff7b72selfTff7b72.Td2a8ffincoming_link_requestTb4b4b4(Te6edf3plaintextTb4b4b4, Te6edf3packetTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3plaintext Tff7b72= Tff7b72selfTff7b72.Td2a8ffdecryptTb4b4b4(Te6edf3packetTff7b72.Td2a8ffdataTb4b4b4)
Te6edf3packetTff7b72.Td2a8ffratchet_id Tff7b72= Tff7b72selfTff7b72.Td2a8fflatest_ratchet_id
Tff7b72if Te6edf3plaintext Tff7b72== Tff7b72NoneTb4b4b4: Tff7b72return Tff7b72False
Tff7b72elseTb4b4b4:
Tff7b72if Te6edf3packetTff7b72.Td2a8ffpacket_type Tff7b72== Te6edf3RNSTff7b72.Td2a8ffPacketTff7b72.Td2a8ffDATATb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffpacket Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4: Tff7b72selfTff7b72.Td2a8ffcallbacksTff7b72.Td2a8ffpacketTb4b4b4(Te6edf3plaintextTb4b4b4, Te6edf3packetTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffError while executing receive callback from Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTb4b4b4)Tff7b72+Ta5d6ff"Ta5d6ff. The contained exception was: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)

Tff7b72return Tff7b72True

Tff7b72def Td2a8ffincoming_link_requestTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3packetTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffaccept_link_requestsTb4b4b4:
Te6edf3link Tff7b72= Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffvalidate_requestTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3packetTb4b4b4)
Tff7b72if Te6edf3link Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8fflinksTff7b72.Td2a8ffappendTb4b4b4(Te6edf3linkTb4b4b4)

Tff7b72def Td2a8ff_reload_ratchetsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3ratchets_pathTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3ratchets_pathTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ffratchet_file_lockTb4b4b4:
Tff7b72def Td2a8ffload_attemptTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3ratchets_file Tff7b72= Tffa657openTb4b4b4(Te6edf3ratchets_pathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4)
Te6edf3persisted_data Tff7b72= Te6edf3umsgpackTff7b72.Td2a8ffunpackbTb4b4b4(Te6edf3ratchets_fileTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72if Ta5d6ff"Ta5d6ffsignatureTa5d6ff" Tff7b72in Te6edf3persisted_data Tff7b72and Ta5d6ff"Ta5d6ffratchetsTa5d6ff" Tff7b72in Te6edf3persisted_dataTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffvalidateTb4b4b4(Te6edf3persisted_dataTb4b4b4[Ta5d6ff"Ta5d6ffsignatureTa5d6ff"Tb4b4b4]Tb4b4b4, Te6edf3persisted_dataTb4b4b4[Ta5d6ff"Ta5d6ffratchetsTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72= Te6edf3umsgpackTff7b72.Td2a8ffunpackbTb4b4b4(Te6edf3persisted_dataTb4b4b4[Ta5d6ff"Ta5d6ffratchetsTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffratchets_path Tff7b72= Te6edf3ratchets_path
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149KeyErrorTb4b4b4(Ta5d6ff"Ta5d6ffInvalid ratchet file signatureTa5d6ff"Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3load_attemptTb4b4b4(Tb4b4b4)

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fftrace_exceptionTb4b4b4(Te6edf3eTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFirst ratchet reload attempt for Tffd700{Tff7b72selfTffd700}Ta5d6ff failed. Possible I/O conflict. Retrying in 500ms.Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.5Tb4b4b4)
Te6edf3load_attemptTb4b4b4(Tb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffRatchet reload retry succeededTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)

Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffratchets_path Tff7b72= Tff7b72None
Te6edf3RNSTff7b72.Td2a8fftrace_exceptionTb4b4b4(Te6edf3eTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffThe ratchet file located at Tffd700{Te6edf3ratchets_pathTffd700}Ta5d6ff could not be loaded. This could indicate that the ratchet file has become corrupt.Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_CRITICALTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffYou can attempt to manually recover the ratchet file, or simply remove it to have Reticulum recreate it on the next use.Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_CRITICALTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffIf re-initialize this ratchet file, make sure to send an announce for the relevant destination as soon as possible,Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_CRITICALTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffso that the new ratchet information is synchronized to the network.Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_CRITICALTb4b4b4)
Tff7b72raise Tf85149OSErrorTb4b4b4(Ta5d6ff"Ta5d6ffCould not read ratchet file contents for Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTb4b4b4)Tff7b72+Ta5d6ff"Ta5d6ff. The contained exception was: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)

Tff7b72elseTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffNo existing ratchet data found, initialising new ratchet file for Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72selfTff7b72.Td2a8ffratchets_path Tff7b72= Te6edf3ratchets_path
Tff7b72selfTff7b72.Td2a8ff_persist_ratchetsTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffenable_ratchetsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3ratchets_pathTb4b4b4)Tb4b4b4:
T8b949e"""
Enables ratchets on the destination. When ratchets are enabled, Reticulum will automatically rotate
the keys used to encrypt packets to this destination, and include the latest ratchet key in announces.

Enabling ratchets on a destination will provide forward secrecy for packets sent to that destination,
even when sent outside a ``Link``. The normal Reticulum ``Link`` establishment procedure already performs
its own ephemeral key exchange for each link establishment, which means that ratchets are not necessary
to provide forward secrecy for links.

Enabling ratchets will have a small impact on announce size, adding 32 bytes to every sent announce.

:param ratchets_path: The path to a file to store ratchet data in.
:returns: True if the operation succeeded, otherwise False.
"""
Tff7b72if Te6edf3ratchets_path Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8fflatest_ratchet_time Tff7b72= T79c0ff0
Tff7b72selfTff7b72.Td2a8ff_reload_ratchetsTb4b4b4(Te6edf3ratchets_pathTb4b4b4)

Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffRatchets enabled on Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72return Tff7b72True

Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffNo ratchet file path specified for Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffenforce_ratchetsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
When ratchet enforcement is enabled, this destination will never accept packets that use its
base Identity key for encryption, but only accept packets encrypted with one of the retained
ratchet keys.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8ffratchets Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff__enforce_ratchets Tff7b72= Tff7b72True
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffRatchets enforced on Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffset_retained_ratchetsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3retained_ratchetsTb4b4b4)Tb4b4b4:
T8b949e"""
Sets the number of previously generated ratchet keys this destination will retain,
and try to use when decrypting incoming packets. Defaults to ``Destination.RATCHET_COUNT``.

:param retained_ratchets: The number of generated ratchets to retain.
:returns: True if the operation succeeded, False if not.
"""
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3retained_ratchetsTb4b4b4, Tffa657intTb4b4b4) Tff7b72and Te6edf3retained_ratchets Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffretained_ratchets Tff7b72= Te6edf3retained_ratchets
Tff7b72selfTff7b72.Td2a8ff_clean_ratchetsTb4b4b4(Tb4b4b4)
Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffset_ratchet_intervalTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3intervalTb4b4b4)Tb4b4b4:
T8b949e"""
Sets the minimum interval in seconds between ratchet key rotation.
Defaults to ``Destination.RATCHET_INTERVAL``.

:param interval: The minimum interval in seconds.
:returns: True if the operation succeeded, False if not.
"""
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3intervalTb4b4b4, Tffa657intTb4b4b4) Tff7b72and Te6edf3interval Tff7b72> T79c0ff0Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffratchet_interval Tff7b72= Te6edf3interval
Tff7b72return Tff7b72True
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72def Td2a8ffcreate_keysTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
For a ``RNS.Destination.GROUP`` type destination, creates a new symmetric key.

:raises: ``TypeError`` if called on an incompatible type of destination.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffPLAINTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffA plain destination does not hold any keysTa5d6ff"Tb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffSINGLETb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffA single destination holds keys through an Identity instanceTa5d6ff"Tb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffGROUPTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffprv_bytes Tff7b72= Te6edf3TokenTff7b72.Td2a8ffgenerate_keyTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffprv Tff7b72= Te6edf3TokenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffprv_bytesTb4b4b4)

Tff7b72def Td2a8ffget_private_keyTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
For a ``RNS.Destination.GROUP`` type destination, returns the symmetric private key.

:raises: ``TypeError`` if called on an incompatible type of destination.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffPLAINTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffA plain destination does not hold any keysTa5d6ff"Tb4b4b4)
Tff7b72elif Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffSINGLETb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffA single destination holds keys through an Identity instanceTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffprv_bytes

Tff7b72def Td2a8ffload_private_keyTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3keyTb4b4b4)Tb4b4b4:
T8b949e"""
For a ``RNS.Destination.GROUP`` type destination, loads a symmetric private key.

:param key: A *bytes-like* containing the symmetric key.
:raises: ``TypeError`` if called on an incompatible type of destination.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffPLAINTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffA plain destination does not hold any keysTa5d6ff"Tb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffSINGLETb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffA single destination holds keys through an Identity instanceTa5d6ff"Tb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffGROUPTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffprv_bytes Tff7b72= Te6edf3key
Tff7b72selfTff7b72.Td2a8ffprv Tff7b72= Te6edf3TokenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffprv_bytesTb4b4b4)

Tff7b72def Td2a8ffload_public_keyTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3keyTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72!= Te6edf3DestinationTff7b72.Td2a8ffSINGLETb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffOnly the Tffea00\"Ta5d6ffsingleTffea00\"Ta5d6ff destination type can hold a public keyTa5d6ff"Tb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149TypeErrorTb4b4b4(Ta5d6ff"Ta5d6ffA single destination holds keys through an Identity instanceTa5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffencryptTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3plaintextTb4b4b4)Tb4b4b4:
T8b949e"""
Encrypts information for ``RNS.Destination.SINGLE`` or ``RNS.Destination.GROUP`` type destination.

:param plaintext: A *bytes-like* containing the plaintext to be encrypted.
:raises: ``ValueError`` if destination does not hold a necessary key for encryption.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffPLAINTb4b4b4:
Tff7b72return Te6edf3plaintext

Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffSINGLE Tff7b72and Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72!= Tff7b72NoneTb4b4b4:
Te6edf3selected_ratchet Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ffget_ratchetTb4b4b4(Tff7b72selfTff7b72.Td2a8ffhashTb4b4b4)
Tff7b72if Te6edf3selected_ratchetTb4b4b4:
Tff7b72selfTff7b72.Td2a8fflatest_ratchet_id Tff7b72= Te6edf3RNSTff7b72.Td2a8ffIdentityTff7b72.Td2a8ff_get_ratchet_idTb4b4b4(Te6edf3selected_ratchetTb4b4b4)
Tff7b72return Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffencryptTb4b4b4(Te6edf3plaintextTb4b4b4, Te6edf3ratchetTff7b72=Te6edf3selected_ratchetTb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffGROUPTb4b4b4:
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff"Ta5d6ffprvTa5d6ff"Tb4b4b4) Tff7b72and Tff7b72selfTff7b72.Td2a8ffprv Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffprvTff7b72.Td2a8ffencryptTb4b4b4(Te6edf3plaintextTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffThe GROUP destination could not encrypt dataTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffThe contained exception was: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffNo private key held by GROUP destination. Did you create or load one?Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffdecryptTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3ciphertextTb4b4b4)Tb4b4b4:
T8b949e"""
Decrypts information for ``RNS.Destination.SINGLE`` or ``RNS.Destination.GROUP`` type destination.

:param ciphertext: *Bytes* containing the ciphertext to be decrypted.
:raises: ``ValueError`` if destination does not hold a necessary key for decryption.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffPLAINTb4b4b4:
Tff7b72return Te6edf3ciphertext

Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffSINGLE Tff7b72and Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffratchetsTb4b4b4:
Te6edf3decrypted Tff7b72= Tff7b72None
Tff7b72tryTb4b4b4:
Te6edf3decrypted Tff7b72= Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffdecryptTb4b4b4(Te6edf3ciphertextTb4b4b4, Te6edf3ratchetsTff7b72=Tff7b72selfTff7b72.Td2a8ffratchetsTb4b4b4, Te6edf3enforce_ratchetsTff7b72=Tff7b72selfTff7b72.Td2a8ff__enforce_ratchetsTb4b4b4, Te6edf3ratchet_id_receiverTff7b72=Tff7b72selfTb4b4b4)
Tff7b72exceptTb4b4b4:
Te6edf3decrypted Tff7b72= Tff7b72None

Tff7b72if Tff7b72not Te6edf3decryptedTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDecryption with ratchets failed on Tffd700{Tff7b72selfTffd700}Ta5d6ff, reloading ratchets from storage and retryingTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_reload_ratchetsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffratchets_pathTb4b4b4)
Te6edf3decrypted Tff7b72= Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffdecryptTb4b4b4(Te6edf3ciphertextTb4b4b4, Te6edf3ratchetsTff7b72=Tff7b72selfTff7b72.Td2a8ffratchetsTb4b4b4, Te6edf3enforce_ratchetsTff7b72=Tff7b72selfTff7b72.Td2a8ff__enforce_ratchetsTb4b4b4, Te6edf3ratchet_id_receiverTff7b72=Tff7b72selfTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDecryption still failing after ratchet reload. The contained exception was: Tffd700{Te6edf3eTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72raise Te6edf3e

Tff7b72if Te6edf3decryptedTb4b4b4: Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffDecryption succeeded after ratchet reloadTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_NOTICETb4b4b4)

Tff7b72return Te6edf3decrypted

Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffdecryptTb4b4b4(Te6edf3ciphertextTb4b4b4, Te6edf3ratchetsTff7b72=Tff7b72NoneTb4b4b4, Te6edf3enforce_ratchetsTff7b72=Tff7b72selfTff7b72.Td2a8ff__enforce_ratchetsTb4b4b4, Te6edf3ratchet_id_receiverTff7b72=Tff7b72selfTb4b4b4)

Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffGROUPTb4b4b4:
Tff7b72if Tffa657hasattrTb4b4b4(Tff7b72selfTb4b4b4, Ta5d6ff"Ta5d6ffprvTa5d6ff"Tb4b4b4) Tff7b72and Tff7b72selfTff7b72.Td2a8ffprv Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffprvTff7b72.Td2a8ffdecryptTb4b4b4(Te6edf3ciphertextTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffThe GROUP destination could not decrypt dataTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffThe contained exception was: Ta5d6ff"Tff7b72+Tffa657strTb4b4b4(Te6edf3eTb4b4b4)Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffNo private key held by GROUP destination. Did you create or load one?Ta5d6ff"Tb4b4b4)

Tff7b72def Td2a8ffsignTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3messageTb4b4b4)Tb4b4b4:
T8b949e"""
Signs information for ``RNS.Destination.SINGLE`` type destination.

:param message: *Bytes* containing the message to be signed.
:returns: A *bytes-like* containing the message signature, or *None* if the destination could not sign the message.
"""
Tff7b72if Tff7b72selfTff7b72.Td2a8fftype Tff7b72== Te6edf3DestinationTff7b72.Td2a8ffSINGLE Tff7b72and Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72!= Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffsignTb4b4b4(Te6edf3messageTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72return Tff7b72None

Tff7b72def Td2a8ffset_default_app_dataTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3app_dataTff7b72=Tff7b72NoneTb4b4b4)Tb4b4b4:
T8b949e"""
Sets the default app_data for the destination. If set, the default
app_data will be included in every announce sent by the destination,
unless other app_data is specified in the *announce* method.

:param app_data: A *bytes-like* containing the default app_data, or a *callable* returning a *bytes-like* containing the app_data.
"""
Tff7b72selfTff7b72.Td2a8ffdefault_app_data Tff7b72= Te6edf3app_data

Tff7b72def Td2a8ffclear_default_app_dataTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""
Clears default app_data previously set for the destination.
"""
Tff7b72selfTff7b72.Td2a8ffset_default_app_dataTb4b4b4(Te6edf3app_dataTff7b72=Tff7b72NoneTb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────